package io.gitee.xjt2016.modules.common;

import lombok.extern.log4j.Log4j2;
import org.springframework.validation.BindException;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.web.bind.MissingPathVariableException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.validation.ConstraintViolation;
import javax.validation.ConstraintViolationException;
import java.util.stream.Collectors;

/**
 * GlobalExceptionHandler.
 * //todo 当前类处理的是 error for json response；如果是页面请求，也要有相应的措施
 *
 * @author xiongjinteng@gmail.com
 */
@Log4j2
@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(NullPointerException.class)
    public Object NPL(NullPointerException ex) {
        log.error("空指针异常", ex);
        WebResponse webResponse = new WebResponse();
        webResponse.setResult(300);
        webResponse.setMessage("空指针异常");
        return webResponse;
    }

    @ExceptionHandler({ConstraintViolationException.class,
            MethodArgumentNotValidException.class,
            ServletRequestBindingException.class,
            BindException.class})
    public Object handleValidationException(Exception e) {
        String message;
        if (e instanceof MethodArgumentNotValidException) {
            MethodArgumentNotValidException t = (MethodArgumentNotValidException) e;
            message = getBindingResultMsg(t.getBindingResult());
        } else if (e instanceof BindException) {
            BindException t = (BindException) e;
            message = getBindingResultMsg(t.getBindingResult());
        } else if (e instanceof ConstraintViolationException) {
            ConstraintViolationException t = (ConstraintViolationException) e;
            message = t.getConstraintViolations().stream()
                    .map(ConstraintViolation::getMessage)
                    .collect(Collectors.joining(","));
        } else if (e instanceof MissingServletRequestParameterException) {
            MissingServletRequestParameterException t = (MissingServletRequestParameterException) e;
            message = t.getParameterName() + " 不能为空";
        } else if (e instanceof MissingPathVariableException) {
            MissingPathVariableException t = (MissingPathVariableException) e;
            message = t.getVariableName() + " 不能为空";
        } else {
            message = "必填参数缺失";
        }
        log.warn("参数校验不通过,msg: {}", message);
        WebResponse webResponse = new WebResponse();
        webResponse.setResult(300);
        webResponse.setMessage(message);
        return webResponse;
    }

    private String getBindingResultMsg(BindingResult bindingResult) {
        return bindingResult.getFieldErrors()
                .stream()
                .map(fieldError -> fieldError.getField() + ":" + fieldError.getDefaultMessage())
                .collect(Collectors.joining(";"));
    }

    @ExceptionHandler(Exception.class)
    public Object globalException(Exception ex) {
        log.error(ex.getMessage(), ex);
        WebResponse webResponse = new WebResponse();
        webResponse.setResult(300);
        webResponse.setMessage("系统异常：" + ex.getMessage());
        return webResponse;
    }

}